﻿using System;
using System.Net;
using System.Runtime.InteropServices;

namespace PingInfo.windows.Converters
{
    public class PingHelperApi
    {
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct ICMP_OPTIONS
        {
            public byte Ttl;
            public byte Tos;
            public byte Flags;
            public byte OptionsSize;
            public uint OptionsData;
        };
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct ICMP_ECHO_REPLY
        {
            public int Address;
            public int Status;
            public int RoundTripTime;
            public short DataSize;
            public short Reserved;
            public uint DataPtr;
            public ICMP_OPTIONS Options;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 250)]
            public string Data;
        }

        public ICMP_OPTIONS oICMPOptions = new ICMP_OPTIONS();
        public ICMP_ECHO_REPLY ICMPReply = new ICMP_ECHO_REPLY();

        [DllImport("iphlpapi.dll", SetLastError = true)]
        private static extern uint IcmpCreateFile();
        [DllImport("iphlpapi.dll", SetLastError = true)]
        private static extern bool IcmpCloseHandle(uint handle);
        [DllImport("iphlpapi.dll", SetLastError = true)]
        private static extern int IcmpSendEcho(uint icmpHandle, uint destinationAddress, string requestData, int requestSize, ref ICMP_OPTIONS requestOptions, ref ICMP_ECHO_REPLY replyBuffer, int replySize, int timeout);
        public bool Ping(IPAddress IP, int timeout = 1000)
        {
            uint ICMPHandle;
            string sData = string.Empty;
            int iReplies;
            ICMPHandle = IcmpCreateFile();
            uint iIP = BitConverter.ToUInt32(IP.GetAddressBytes(), 0);
            var sTemp = "x";
            for (int i = 0; i < 32; i++)
            {
                sData += sTemp;
            }
            oICMPOptions.Ttl = 255;
            iReplies = IcmpSendEcho(ICMPHandle, iIP, sData, sData.Length, ref oICMPOptions, ref ICMPReply, Marshal.SizeOf(ICMPReply), timeout);
            IcmpCloseHandle(ICMPHandle);
            return iReplies == 1;
        }
    }
}

